//
// Created by Hoyin on 2024/1/26.
//
#include "utils.h"
#include <fstream>


using namespace utl;
using namespace std;

void utl::showImage(const char *winName, cv::Mat image, int delay) {
	cv::imshow(winName, image);
	cv::waitKey(delay);
}

void utl::showImages(const std::string &winNamePrefix, std::vector<cv::Mat> images, int delay) {
	for (size_t i = 0; i < images.size(); i++) {
		const std::string winName = winNamePrefix + "_" + std::to_string(i);
		cv::Mat& image = images.at(i);
		if (image.empty()) {
			std::cerr << "Empty image at " << i << std::endl;
			continue;
		}
		showImage(winName.c_str(), image, delay);
	}
}

void utl::getBitPattern(const char *bitPatternFile, int bitPattern[]) {
	std::ifstream file(bitPatternFile);
	if (!file.is_open()) {
		std::cerr << "Cannot open file: " << bitPatternFile << std::endl;
		return;
	}

	std::string line;
	int idx = 0;
	while (!file.eof()) {
		file >> bitPattern[idx++];
	}

	file.close();
}

void utl::ransac(std::vector<cv::DMatch> matches, std::vector<cv::KeyPoint> queryKeyPoint,
            std::vector<cv::KeyPoint> trainKeyPoint, std::vector<cv::DMatch> &matches_ransac) {
//	定义保存匹配点对坐标
	std::vector<cv::Point2f> srcPoints(matches.size()), dstPoints(matches.size());
//	保存从关键点中提取到的匹配点坐标
	for (int i = 0; i < matches.size(); i++) {
		srcPoints[i] = queryKeyPoint[matches[i].queryIdx].pt;
		dstPoints[i] = trainKeyPoint[matches[i].trainIdx].pt;
	}
//  匹配点对进行RANSAC过滤
	std::vector<int> inliersMask(srcPoints.size());
	cv::findHomography(srcPoints, dstPoints, cv::RANSAC, 10, inliersMask);
	for (int i = 0; i < inliersMask.size(); i++) {
		if (inliersMask[i]) {
			matches_ransac.push_back(matches[i]);
		}
	}
}

std::stringstream utl::readFile(const std::string &file) {
//	定义文件输入流
	ifstream inputFS(file);
	if (!inputFS.good()) {
		stringstream ss;
		ss << "failed";
		return ss;
	}
//	获取配置全文
	stringstream ss;
	char ch;
	while (!inputFS.eof()) {
		inputFS.get(ch);
		ss << ch;
	}
	inputFS.close();
	return ss;
}

void utl::initializeOrbPattern(const cv::Point *pattern0, std::vector<cv::Point> &pattern, int ntuples, int tupleSize, int poolSize) {
	cv::RNG rng(0x12345678);
	int i, k, k1;
	pattern.resize(ntuples*tupleSize);

	for( i = 0; i < ntuples; i++ )
	{
		for( k = 0; k < tupleSize; k++ )
		{
			for(;;)
			{
				int idx = rng.uniform(0, poolSize);
				cv::Point pt = pattern0[idx];
				for( k1 = 0; k1 < k; k1++ )
					if( pattern[tupleSize*i + k1] == pt )
						break;
				if( k1 == k )
				{
					pattern[tupleSize*i + k] = pt;
					break;
				}
			}
		}
	}
}

void utl::drawBarChart(Eigen::VectorXi &vec, cv::Mat &dst) {
	int size = vec.size();
	int max_value = vec.maxCoeff();

	int width = 1;
	int height = 300;
	dst = cv::Mat(height, size * width, CV_8UC3, cv::Scalar(255, 255, 255));

	for (int i = 0; i < size; ++i) {
		int bar_height = static_cast<int>((static_cast<double>(vec[i]) / max_value) * height * 0.9);
		cv::rectangle(dst, cv::Point(i * width, height - bar_height), cv::Point((i + 1) * width - 1, height), cv::Scalar(66, 104, 139), -1);
	}
}

void utl::drawText(const string &text, cv::Mat &canvas, const cv::Point &pos, const cv::Scalar &color, cv::Scalar &fillColor,
              double fontScale, int anchor) {
	int baseline;
	cv::Size textSize = cv::getTextSize(text, cv::FONT_HERSHEY_COMPLEX, fontScale, 1, &baseline);
	cv::Point _pos(pos);
	switch (anchor) {
		case TextAnchor::TOP_LEFT:
			_pos += cv::Point(0, 0);
			break;
		case TextAnchor::TOP_RIGHT:
			_pos += cv::Point(-textSize.width, 0);
			break;
		case TextAnchor::BOTTOM_LEFT:
			_pos += cv::Point(0, -textSize.height);
			break;
		case TextAnchor::BOTTOM_RIGHT:
			_pos += cv::Point(-textSize.width, -textSize.height);
			break;
		default:
			break;
	}

	cv::Point textPos(_pos.x, _pos.y+textSize.height);
	if (0 <= fillColor[0] && fillColor[0] <= 255 &&
	    0 <= fillColor[1] && fillColor[1] <= 255 &&
	    0 <= fillColor[2] && fillColor[2] <= 255) {
		cv::Size rectSize(textSize);
		rectSize.height += baseline;
		cv::rectangle(canvas, cv::Rect(_pos, rectSize), fillColor, cv::FILLED);
	}
	cv::putText(canvas, text, textPos, cv::FONT_HERSHEY_COMPLEX, fontScale, color, 1);
}

